Skip to content

[refactor] redesign User profile page & fix Activity create layout#27

Merged
TechQuery merged 7 commits into
mainfrom
feat/auth
May 3, 2026
Merged

[refactor] redesign User profile page & fix Activity create layout#27
TechQuery merged 7 commits into
mainfrom
feat/auth

Conversation

@dethan3
Copy link
Copy Markdown
Contributor

@dethan3 dethan3 commented Dec 15, 2025

PR-27 PR-27 PR-27 Powered by Pull Request Badge

  • Redesign /me and /user/[id] pages with modern hero sections (resolve 现代化 HOP(黑客松开放平台)个人主页 UI 样式 #32)
  • Fix avatar clipping by moving avatars outside overflow containers
  • Use Bootstrap utility classes for responsive styling
  • Adjust activity/create editor to responsive column layout
  • Fix hydration error on /me page by using SSR props directly

Checklist:

  • Labels
  • Assignees
  • Reviewers

Summary by CodeRabbit

Release Notes

  • New Features

    • Redesigned user profile pages with hero section, improved owner-only controls, and better layout
    • Added authenticated user profile redirect page
  • Bug Fixes

    • Enhanced OAuth configuration validation with runtime error handling
  • Documentation

    • Added GitHub OAuth setup instructions and environment configuration guide
  • Chores

    • Updated app branding and naming across platform
    • Improved sign-out functionality with secure cookie handling

- Redesign /me and /user/[id] pages with modern hero sections
- Fix avatar clipping by moving avatars outside overflow containers
- Use Bootstrap utility classes for responsive styling
- Adjust activity/create editor to responsive column layout
- Fix hydration error on /me page by using SSR props directly
@dethan3 dethan3 added the enhancement Some improvements label Dec 15, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 15, 2025

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR modernizes the user profile page UI, enhances session management with async cleanup and secure cookies, updates activity creation page layout, implements a profile redirect middleware, adds GitHub OAuth configuration documentation, and consolidates branding strings and configuration exports across the application.

Changes

Authentication System Enhancement

Layer / File(s) Summary
Dependency & Configuration
package.json, configuration/index.ts
Adds idb-keyval dependency for IndexedDB clearing; exports NODE_ENV and derives new isProduction constant.
Session Model
models/User/Session.ts
SessionModel.signOut() converted to async: after clearing cookies and setting user = undefined, awaits sleep() then clears IndexedDB via idb-keyval.clear().
API JWT & OAuth Validation
pages/api/core.ts
JWT cookie now includes conditional Secure and SameSite=Lax attributes based on isProduction; adds runtime checks for GITHUB_OAUTH_CLIENT_ID and GITHUB_OAUTH_CLIENT_SECRET with explicit error messages.
UI Sign-Out Flow
components/User/UserBar.tsx
Ternary conditional to show account dropdown when authenticated, else sign-in button; edit-profile and sign-out menu items call sessionStore.signOut() with appropriate flags.
Profile Auto-Fetch & Redirect
pages/_app.tsx, pages/user/me.tsx
App component calls sessionStore.getProfile() on mount; new /user/me page redirects to user profile by ID if authenticated.
Documentation
README.md
Adds "Environment Configuration" section with GitHub OAuth setup instructions and required .env variables.

User Profile Page Modernization

Layer / File(s) Summary
Data Shape & Types
pages/user/[id].tsx
Introduces PublicUser type omitting sensitive fields; getServerSideProps filters and returns only public user data.
Page Layout & Logic
pages/user/[id].tsx
Redesigns from flat structure to hero section (badge, name, optional email) + two-column layout; computes isOwner and conditional visibility for email/phone; replaces old Tabs with Tab.Container using enrolled/created/admin event keys.
Profile Card & Actions
pages/user/[id].tsx
Left column renders avatar Image or placeholder; owner-only email/phone links and edit-profile button (with pencil icon) linking to GitHub settings and triggering sign-out.
Styling
pages/user/[id].module.less
New .hero-section with radial gradient; .avatar-placeholder (120×120 gradient); .social-btn with hover/active states; .custom-tabs with styled nav links and transitions.

Activity Creation Page Layout

Layer / File(s) Summary
Layout Structure
pages/activity/create.tsx
Changes from centered Card with mx-auto to responsive Bootstrap Container > Row > Col (lg=10, xl=8) with ActivityEditor inside a rounded Card.
Styling Cleanup
pages/activity/create.module.less
Removes position, z-index, negative margin-top, border-radius, and background; retains only box-shadow.

Branding & Localization

Layer / File(s) Summary
Environment & Manifest
.env, public/manifest.json
Updates NEXT_PUBLIC_SITE_NAME and app name/short_name from "开放黑客松" to "黑客松开放" variants.
Locale Strings
translation/zh-CN.ts, translation/zh-TW.ts, translation/en-US.ts
Aligns all UI text: open_hackathon_platform and hero_subtitle reworded to match new branding; English string updated to "Open Hackathon Platform".

Infrastructure Updates

Layer / File(s) Summary
TypeScript Configuration
tsconfig.json
Changes moduleResolution from "Node" to "bundler".
Model Refactoring
models/Activity/Award.ts
AwardModel now extends TableModel<Award> instead of Stream<Award>(ListModel); constructor parameter becomes public parameter property.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • TechQuery

Poem

🐰 Through sessions cleared with IndexedDB's grace,
Profile pages bloom with modern face,
Buttons glow, tabs dance, and branding shines,
OAuth flows now guard each login line,
The platform grows its open-hackathon spine! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Some changes extend beyond the profile UI redesign scope: environment variable documentation, JWT cookie security improvements, IndexedDB session clearing, package dependency additions, and TypeScript configuration updates appear unrelated to the primary profile redesign objective. Review and separate unrelated changes (env vars, security updates, config changes) into dedicated PRs focused on their specific concerns, keeping this PR focused on profile redesign.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR successfully implements the modernized UI design for profile pages (#32). Changes include hero sections, responsive layouts, and updated styling that align with contemporary design practices and the stated objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title accurately summarizes the main changes: redesigning the user profile page and fixing the activity create layout. Both aspects are prominently reflected in the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/auth

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pages/api/core.ts (1)

84-89: Harden JWT cookie with HttpOnly/Secure/SameSite flags

The JWT session token is currently set without any security flags:

res.setHeader('Set-Cookie', `JWT=${user.token}; Path=/`);

This makes the token readable from JavaScript and more exposed to XSS and CSRF‑style attacks. Add HttpOnly, Secure (in production), and SameSite flags:

-    res.setHeader('Set-Cookie', `JWT=${user.token}; Path=/`);
+    const isProd = process.env.NODE_ENV === 'production';
+    res.setHeader(
+      'Set-Cookie',
+      [
+        `JWT=${user.token}`,
+        'Path=/',
+        'HttpOnly',
+        isProd ? 'Secure' : '',
+        'SameSite=Lax',
+      ]
+        .filter(Boolean)
+        .join('; '),
+    );

This significantly reduces the blast radius if any XSS occurs and improves CSRF resistance for JWT‑backed requests.

🧹 Nitpick comments (4)
pages/login.tsx (1)

17-24: Consider hydration error prevention and error handling.

The redirect logic looks correct, but consider these improvements:

  1. Effect cleanup: If the component unmounts during redirect (e.g., user navigates away), the router.replace could throw. Consider adding cleanup or error handling.

  2. Session storage timing: Direct assignment on Line 19 (sessionStore.user = jwtPayload) happens before the redirect completes. If the target page immediately reads session state, ensure MobX reactivity has settled.

  3. No-op when jwtPayload is absent: The effect only runs when jwtPayload exists, which is correct. However, consider what happens if a user reaches this page without a valid session—should there be a fallback UI or redirect to home?

Consider adding error boundary or try-catch:

  useEffect(() => {
    if (jwtPayload) {
      sessionStore.user = jwtPayload;

      const targetUrl = typeof redirect === 'string' ? redirect : '/';
-     router.replace(targetUrl);
+     router.replace(targetUrl).catch(error => {
+       console.error('Redirect failed:', error);
+     });
    }
  }, [jwtPayload, redirect, router]);
pages/me/index.tsx (1)

48-68: Optional: consider factoring repeated avatar/action patterns into shared components

The avatar block and some of the action button patterns overlap conceptually with /user/[id].tsx. Extracting a small Avatar and/or ProfileActions component could reduce duplication and keep behavior (e.g., future avatar sizing or styling tweaks) consistent across pages.

Also applies to: 166-188

pages/user/[id].tsx (2)

75-89: GitHub link assumes name is a username; consider using an explicit field or guarding

The GitHub button currently links to:

href={`https://github.com/${name}`}

This only works reliably if name is guaranteed to be the GitHub handle. In many user models, name is a display name, which can contain spaces or non‑ASCII characters and won’t map cleanly to a GitHub profile URL.

Consider either:

  • Using an explicit githubLogin (or similar) field from User, if available, or
  • Guarding the link so it’s only active when you have a valid GitHub handle, e.g.:
-  <a
-    href={`https://github.com/${name}`}
+  {name && (
+    <a
+      href={`https://github.com/${encodeURIComponent(name)}`}
       target="_blank"
       rel="noreferrer"
       ...
-  >
-    <Icon name="github" />
-  </a>
+    >
+      <Icon name="github" />
+    </a>
+  )}

This avoids obviously broken or misleading links for users whose name isn’t their GitHub username.


90-120: Optional: clarify placeholder social buttons to avoid implying wired accounts

The QQ/WeChat/Weibo icons are rendered as styled <span> elements without any actual linking or behavior. Visually they look like active buttons, which can confuse users if they click and nothing happens.

If these are placeholders for future work, consider:

  • Reducing opacity / disabling pointer events, or
  • Hiding them until real profile data (e.g., qq, wechat, weibo) is available.

That keeps the UI honest about which socials are actually connected.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between af47000 and 85b7901.

📒 Files selected for processing (14)
  • .env.development (1 hunks)
  • README.md (1 hunks)
  • components/User/UserBar.tsx (2 hunks)
  • docs/TASKS.md (1 hunks)
  • models/User/Session.ts (1 hunks)
  • pages/_app.tsx (2 hunks)
  • pages/activity/create.module.less (0 hunks)
  • pages/activity/create.tsx (1 hunks)
  • pages/api/core.ts (1 hunks)
  • pages/login.tsx (1 hunks)
  • pages/me/index.module.less (1 hunks)
  • pages/me/index.tsx (1 hunks)
  • pages/user/[id].module.less (1 hunks)
  • pages/user/[id].tsx (2 hunks)
💤 Files with no reviewable changes (1)
  • pages/activity/create.module.less
🧰 Additional context used
🧬 Code graph analysis (5)
pages/me/index.tsx (5)
pages/activity/create.tsx (1)
  • getServerSideProps (14-14)
pages/login.tsx (1)
  • getServerSideProps (11-11)
pages/user/[id].tsx (1)
  • getServerSideProps (19-24)
pages/api/core.ts (1)
  • sessionGuard (115-115)
models/Base/Translation.ts (1)
  • I18nContext (44-44)
pages/login.tsx (4)
pages/activity/create.tsx (1)
  • getServerSideProps (14-14)
pages/me/index.tsx (1)
  • getServerSideProps (15-15)
pages/api/core.ts (1)
  • sessionGuard (115-115)
components/layout/PageHead.tsx (1)
  • PageHead (11-19)
components/User/UserBar.tsx (1)
components/layout/MainNavigation.tsx (1)
  • () => import('../User/UserBar') (10-10)
models/User/Session.ts (1)
configuration/index.ts (3)
  • API_HOST (10-10)
  • isServer (3-3)
  • globalThis (12-15)
pages/api/core.ts (3)
configuration/index.ts (1)
  • process (8-8)
models/Git.ts (1)
  • next (15-21)
next.config.ts (1)
  • beforeFiles (25-38)
🪛 dotenv-linter (4.0.0)
.env.development

[warning] 4-4: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)

🔇 Additional comments (8)
README.md (1)

29-57: LGTM! Clear and comprehensive setup documentation.

The environment configuration section provides excellent guidance for developers. The OAuth setup instructions are particularly helpful.

pages/activity/create.tsx (1)

33-45: LGTM! Well-structured responsive layout.

The Bootstrap grid implementation is clean and follows best practices. The responsive column sizing (lg=10, xl=8) provides appropriate width constraints for the form.

docs/TASKS.md (1)

1-191: LGTM! Excellent project planning documentation.

The task breakdown is comprehensive and well-structured, with clear acceptance criteria and scope definitions for each milestone. This will help maintain organized development flow.

pages/me/index.module.less (1)

1-18: LGTM! Clean styling module.

The styles are well-structured with appropriate transitions and theming. The gradient and hover effects enhance the UI.

pages/user/[id].module.less (1)

1-46: LGTM! Consistent styling with good interaction states.

The styling module provides good visual feedback with transitions and hover states. The use of :global selectors for Bootstrap classes is appropriate.

pages/me/index.tsx (1)

17-27: Session source and hydration behavior look sound

Using jwtPayload from getServerSideProps as the primary user source and mirroring it into sessionStore.user in useEffect, while resolving user = jwtPayload || sessionStore.user, avoids hydration mismatches and still keeps the MobX store in sync. The null fallback when user is missing is a reasonable guard given sessionGuard should already handle redirects.

components/User/UserBar.tsx (1)

14-18: Login redirect handling is correct locally; verify server-side validation

loginUrl correctly encodes router.asPath, and the UI cleanly distinguishes authenticated (dropdown) vs unauthenticated (GitHub sign‑in button) states. The only remaining concern is how /login consumes the redirect query:

  • If /login blindly redirects to redirect, a crafted URL could potentially be used for open redirects.
  • Ideally, the login handler should allow only internal paths and ignore or sanitize absolute URLs.

Given that logic lives outside this file, please confirm /pages/login.tsx validates redirect as an internal path before using it.

Also applies to: 25-49

pages/_app.tsx (1)

14-16: > Likely an incorrect or invalid review comment.

Comment thread .env.development Outdated
Comment thread models/User/Session.ts Outdated
Comment thread pages/api/core.ts
Copy link
Copy Markdown
Member

@TechQuery TechQuery left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

先合并主分支更新、安装最新依赖后,再改代码。

Comment thread pages/api/core.ts Outdated
Comment thread pages/api/core.ts Outdated
Comment thread pages/me/index.tsx Outdated
Comment thread components/User/UserBar.tsx Outdated
Comment thread pages/_app.tsx Outdated
Comment thread pages/login.tsx Outdated
Comment thread README.md
Comment thread README.md Outdated
Comment thread models/User/Session.ts Outdated
Comment thread .env.development Outdated
- fix(.env.development): remove spaces around = in env var assignments
- fix(api/core): harden JWT cookie with HttpOnly, SameSite=Lax, Secure(prod)
- fix(Session): suppress redundant error re-throw after 401/403 redirect
- fix(login): add .catch() on router.replace() and guard against open redirect
- fix(user/[id]): guard GitHub link with conditional render + encodeURIComponent
- fix(user/[id]): remove placeholder social buttons with no backing data
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
models/User/Session.ts (1)

22-28: ⚠️ Potential issue | 🟡 Minor

Consider redirecting only on 401, not 403.

Per the project maintainer's feedback, 401 indicates the user is unauthenticated (JWT invalid/expired), while 403 means the resource is forbidden for the current user. Redirecting to login on 403 is inappropriate since re-authenticating won't grant access to a forbidden resource.

-        if (status === 401 || status === 403) {
+        if (status === 401) {

Additionally, ESLint flags a missing blank line before the return statement on line 28.

           globalThis.location?.assign(loginUrl);
+
           return;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@models/User/Session.ts` around lines 22 - 28, Change the status check so only
a 401 triggers a client-side redirect (i.e., replace the combined check `if
(status === 401 || status === 403)` with `if (status === 401)`), leaving 403
handling untouched; keep the existing logic that builds `currentPath`,
`loginUrl`, and calls `globalThis.location?.assign(loginUrl)`. Also add the
missing blank line before the `return` statement inside this block to satisfy
the ESLint rule. Locate this change in the session/auth handling block where
`status`, `isServer()`, `currentPath`, `loginUrl`, and
`globalThis.location?.assign` are used.
🧹 Nitpick comments (1)
pages/login.tsx (1)

1-9: Fix import order per ESLint.

ESLint flags the imports need sorting. Run autofix to resolve.

 import { User } from '@freecodecamp-chengdu/hop-service';
 import { JWTProps } from 'next-ssr-middleware';
 import { useRouter } from 'next/router';
 import { FC, useEffect } from 'react';
 import { Container, Spinner } from 'react-bootstrap';

 import { PageHead } from '../components/layout/PageHead';
+import { sessionGuard } from './api/core';
 import sessionStore from '../models/User/Session';
-import { sessionGuard } from './api/core';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pages/login.tsx` around lines 1 - 9, Reorder the import statements in this
module to satisfy ESLint import-sorting: group and sort them
(builtin/third-party first alphabetically, then local project imports) so that
imports like "react" hooks (useEffect, FC), "next" packages (useRouter),
"@freecodecamp-chengdu/hop-service" (User), "next-ssr-middleware" (JWTProps),
"react-bootstrap" (Container, Spinner) appear before project-local imports
(PageHead, sessionStore, sessionGuard) and ensure each import line is
alphabetized within its group; you can run the project's ESLint autofix or
manually reorder the imports to match the linter's expected order (refer to the
imported symbols User, JWTProps, useRouter, FC, useEffect, Container, Spinner,
PageHead, sessionStore, sessionGuard).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pages/user/`[id].tsx:
- Around line 26-39: UserDetailPage currently renders the raw email prop
directly (props: id, name, avatar, email) in two places; change it to
conditionally display the email only when the viewer is authorized (e.g., viewer
is the profile owner or the user has opted into public email) or else show a
masked/stubbed string. Update the UserDetailPage component to (1) obtain viewer
context (e.g., currentUser from AuthContext or similar), (2) implement a small
helper check like isOwnerOrConsented = currentUser?.id === id ||
user?.showEmailConsent, and (3) replace direct uses of {email} at both render
sites with a conditional that either shows the real email (or a mailto link)
when isOwnerOrConsented is true or a masked placeholder (e.g., "email hidden")
otherwise.
- Around line 77-90: The anchor rendering the icon-only social link (the <a>
around <Icon name="github" />) lacks an explicit accessible name for screen
readers; add an aria-label (or aria-labelledby) to that anchor—e.g., "GitHub" or
a more descriptive "GitHub profile for {name}"—so assistive tech has a reliable
name in addition to the visual icon and existing title attribute; update the
anchor element where classNames/styles and title="GitHub" are set to include the
aria attribute.
- Around line 76-79: The UI is linking to GitHub using User.name which is a
display name, not a guaranteed GitHub login; update the data shape and usages to
use a dedicated githubLogin (or github_login) field on the User type and replace
occurrences of user.name (including the link in pages/user/[id].tsx and the
addCollaborator(...) call) with user.githubLogin; if you cannot change the
upstream type immediately, add a validation/fetch step where the page loads
(e.g., in the user data loader or useEffect that fetches user details) to
resolve/verify the actual GitHub username via your user service or GitHub API
and only render the anchor or call addCollaborator when a validated githubLogin
exists, falling back to hiding the link and preventing addCollaborator from
using display name.

---

Duplicate comments:
In `@models/User/Session.ts`:
- Around line 22-28: Change the status check so only a 401 triggers a
client-side redirect (i.e., replace the combined check `if (status === 401 ||
status === 403)` with `if (status === 401)`), leaving 403 handling untouched;
keep the existing logic that builds `currentPath`, `loginUrl`, and calls
`globalThis.location?.assign(loginUrl)`. Also add the missing blank line before
the `return` statement inside this block to satisfy the ESLint rule. Locate this
change in the session/auth handling block where `status`, `isServer()`,
`currentPath`, `loginUrl`, and `globalThis.location?.assign` are used.

---

Nitpick comments:
In `@pages/login.tsx`:
- Around line 1-9: Reorder the import statements in this module to satisfy
ESLint import-sorting: group and sort them (builtin/third-party first
alphabetically, then local project imports) so that imports like "react" hooks
(useEffect, FC), "next" packages (useRouter),
"@freecodecamp-chengdu/hop-service" (User), "next-ssr-middleware" (JWTProps),
"react-bootstrap" (Container, Spinner) appear before project-local imports
(PageHead, sessionStore, sessionGuard) and ensure each import line is
alphabetized within its group; you can run the project's ESLint autofix or
manually reorder the imports to match the linter's expected order (refer to the
imported symbols User, JWTProps, useRouter, FC, useEffect, Container, Spinner,
PageHead, sessionStore, sessionGuard).

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 85b7901 and b1c1aa9.

📒 Files selected for processing (5)
  • .env.development
  • models/User/Session.ts
  • pages/api/core.ts
  • pages/login.tsx
  • pages/user/[id].tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • .env.development

Comment thread pages/user/[id].tsx Outdated
Comment thread pages/user/[id].tsx Outdated
Comment thread pages/user/[id].tsx Outdated
Copy link
Copy Markdown
Member

@TechQuery TechQuery left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dethan3 你有好几处点 resolve 的 review 意见并没有提交代码变更……

Comment thread pages/api/core.ts Outdated
Comment thread .env.development
Comment thread pages/user/[id].tsx Outdated
Comment thread docs/TASKS.md Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pages/user/[id].tsx (1)

20-25: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

email (and mobilePhone) are still exposed in __NEXT_DATA__ despite the client-side guard.

getServerSideProps returns the full User object. Next.js serializes all returned props into <script id="__NEXT_DATA__"> in the HTML, which is visible to anyone who views page source or inspects the network response — regardless of whether the fields are rendered on screen. The visibleEmail / isOwner guard introduced in the component only hides the display; it does not prevent the data from being embedded in the page payload. With cache() active, this cached payload is served to every visitor.

Explicitly omit sensitive fields before returning from getServerSideProps:

🔒 Proposed fix
  async ({ params: { id = '' } = {} }) => {
-   JSON.parse(JSON.stringify({ props: await userStore.getOne(id) })),
+   const { email: _email, mobilePhone: _phone, password: _pw, ...safeUser } =
+     await userStore.getOne(id);
+   return JSON.parse(JSON.stringify({ props: safeUser }));
  },

With sensitive fields removed from SSR props, update the component to source email exclusively from sessionStore.user (already done for mobilePhone):

-const UserDetailPage: FC<User> = observer(({ id, name, avatar, email }) => {
+const UserDetailPage: FC<Omit<User, 'email' | 'mobilePhone' | 'password'>> = observer(({ id, name, avatar }) => {
   const { t } = useContext(I18nContext);
   const isOwner = sessionStore.user?.id === id;
-  const visibleEmail = isOwner ? sessionStore.user?.email || email : undefined;
+  const visibleEmail = isOwner ? sessionStore.user?.email : undefined;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pages/user/`[id].tsx around lines 20 - 25, getServerSideProps is returning
the full User from userStore.getOne(id) which embeds sensitive fields (email,
mobilePhone) into the serialized __NEXT_DATA__; fetch the user via
userStore.getOne(id) inside the compose async handler, construct a sanitized
object that omits email and mobilePhone (or explicitly picks only public
fields), and return JSON.stringify/JSON.parse of { props: sanitizedUser }
instead of the raw User; keep compose, cache(), and errorLogger intact and
ensure the page component sources email only from sessionStore.user while
mobilePhone is also excluded from SSR props.
🧹 Nitpick comments (2)
pages/user/[id].tsx (2)

112-145: ⚡ Quick win

All three Tab.Panes (and their ActivityList API calls) mount eagerly on page load.

React-Bootstrap renders all Tab.Pane children immediately by default, even non-active ones. This triggers three ActivityList data fetches on mount instead of one. Adding mountOnEnter to Tab.Container defers the two inactive panes until they are first visited:

⚡ Proposed fix
-<Tab.Container defaultActiveKey="enrolled">
+<Tab.Container defaultActiveKey="enrolled" mountOnEnter>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pages/user/`[id].tsx around lines 112 - 145, Tab panes (Tab.Pane) are all
mounting eagerly causing three ActivityList API calls on page load; update the
Tab.Container component (where Tab.Container is declared) to add the
mountOnEnter prop so inactive Tab.Pane children defer mounting until first
visited, ensuring ActivityList (type="enrolled"/"created"/"admin") only fetches
when its pane is entered.

1-14: ⚡ Quick win

Fix ESLint import sort error.

The static analysis tool reports an error on these imports (simple-import-sort/imports). Run eslint --fix to auto-sort them and unblock CI.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pages/user/`[id].tsx around lines 1 - 14, The import statements in
pages/user/[id].tsx are out of order and trigger the simple-import-sort/imports
ESLint rule; run eslint --fix or manually reorder imports so builtin/react
imports come first, then external packages (e.g., classNames, idea-react,
mobx-react, next, next-ssr-middleware), then local modules (e.g., PageHead,
I18nContext, sessionStore, userStore, styles), ensuring grouped and alphabetized
order; after reordering, re-run lint to confirm the error for the module imports
(Icon, observer, dynamic, cache/compose/errorLogger, FC/useContext,
Badge/Button/Card/etc.) is resolved.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pages/user/`[id].tsx:
- Around line 27-30: The current isOwner calculation in UserDetailPage (using
sessionStore.user) causes a hydration mismatch because sessionStore is empty
during SSR; instead defer ownership detection until after hydration by
introducing client-only state: create a useState flag (e.g., isOwner)
initialized to false and set it inside a useEffect that compares
sessionStore.user?.id with the page prop id, then use that flag for visibleEmail
and owner-only UI. Update references to isOwner and visibleEmail so they rely on
the post-hydration state (and keep the SSR-rendered HTML unaffected).

---

Outside diff comments:
In `@pages/user/`[id].tsx:
- Around line 20-25: getServerSideProps is returning the full User from
userStore.getOne(id) which embeds sensitive fields (email, mobilePhone) into the
serialized __NEXT_DATA__; fetch the user via userStore.getOne(id) inside the
compose async handler, construct a sanitized object that omits email and
mobilePhone (or explicitly picks only public fields), and return
JSON.stringify/JSON.parse of { props: sanitizedUser } instead of the raw User;
keep compose, cache(), and errorLogger intact and ensure the page component
sources email only from sessionStore.user while mobilePhone is also excluded
from SSR props.

---

Nitpick comments:
In `@pages/user/`[id].tsx:
- Around line 112-145: Tab panes (Tab.Pane) are all mounting eagerly causing
three ActivityList API calls on page load; update the Tab.Container component
(where Tab.Container is declared) to add the mountOnEnter prop so inactive
Tab.Pane children defer mounting until first visited, ensuring ActivityList
(type="enrolled"/"created"/"admin") only fetches when its pane is entered.
- Around line 1-14: The import statements in pages/user/[id].tsx are out of
order and trigger the simple-import-sort/imports ESLint rule; run eslint --fix
or manually reorder imports so builtin/react imports come first, then external
packages (e.g., classNames, idea-react, mobx-react, next, next-ssr-middleware),
then local modules (e.g., PageHead, I18nContext, sessionStore, userStore,
styles), ensuring grouped and alphabetized order; after reordering, re-run lint
to confirm the error for the module imports (Icon, observer, dynamic,
cache/compose/errorLogger, FC/useContext, Badge/Button/Card/etc.) is resolved.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: de905dea-3310-459d-ab31-346736ef890b

📥 Commits

Reviewing files that changed from the base of the PR and between b1c1aa9 and a10aca3.

📒 Files selected for processing (11)
  • .env
  • .env.development
  • README.md
  • components/User/UserBar.tsx
  • configuration/index.ts
  • models/User/Session.ts
  • pages/api/core.ts
  • pages/user/[id].tsx
  • public/manifest.json
  • translation/zh-CN.ts
  • translation/zh-TW.ts
✅ Files skipped from review due to trivial changes (7)
  • .env.development
  • public/manifest.json
  • README.md
  • configuration/index.ts
  • translation/zh-TW.ts
  • models/User/Session.ts
  • translation/zh-CN.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • pages/api/core.ts

Comment thread pages/user/[id].tsx Outdated
Comment thread components/User/UserBar.tsx
Comment thread components/User/UserBar.tsx
Comment thread configuration/index.ts Outdated
Comment thread pages/api/core.ts Outdated
Comment thread pages/api/core.ts Outdated
Comment thread pages/user/[id].tsx Outdated
Comment thread public/manifest.json Outdated
Comment thread translation/zh-CN.ts Outdated
Comment thread .env.development
Comment thread README.md Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@public/manifest.json`:
- Around line 2-3: The site name is inconsistent: manifest.json sets "name":
"黑客松开放平台" and "short_name": "开源黑客松" while the runtime env var
NEXT_PUBLIC_SITE_NAME is "黑客松开放"; update the canonical name to be consistent
across both places — choose the preferred product name and then update the
manifest keys ("name" and/or "short_name") and the environment variable
NEXT_PUBLIC_SITE_NAME to match that exact string so the manifest and runtime use
the same branding.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c64150b8-809c-4e53-82b8-4a8bf7dc1064

📥 Commits

Reviewing files that changed from the base of the PR and between a10aca3 and b2c26b9.

📒 Files selected for processing (10)
  • README.md
  • components/User/UserBar.tsx
  • configuration/index.ts
  • pages/api/core.ts
  • pages/user/[id].module.less
  • pages/user/[id].tsx
  • public/manifest.json
  • translation/en-US.ts
  • translation/zh-CN.ts
  • translation/zh-TW.ts
✅ Files skipped from review due to trivial changes (4)
  • translation/en-US.ts
  • translation/zh-CN.ts
  • translation/zh-TW.ts
  • README.md

Comment thread public/manifest.json
Co-authored-by: Copilot <copilot@github.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
pages/user/[id].tsx (1)

114-121: Handle the async signOut() promise explicitly on Line 120.

sessionStore.signOut() is async and calls clear() from idb-keyval without internal error handling. If the IndexedDB operation fails, the returned promise will reject, causing an unhandled rejection. This pattern occurs at all three call sites (pages/user/[id].tsx:120, components/User/UserBar.tsx:30, and components/User/UserBar.tsx:35).

♻️ Minimal safe tweak
-                    onClick={() => sessionStore.signOut()}
+                    onClick={() => {
+                      void sessionStore.signOut().catch((error) => {
+                        console.error('Sign out failed:', error);
+                      });
+                    }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pages/user/`[id].tsx around lines 114 - 121, The onClick currently calls the
async sessionStore.signOut() without awaiting or handling rejections; update
each call site (sessionStore.signOut() in pages/user/[id].tsx and both
occurrences in components/User/UserBar.tsx) to explicitly handle the returned
promise — either make the onClick handler async and await sessionStore.signOut()
inside a try/catch that logs or handles errors, or append .catch(...) to the
promise to swallow/log failures; ensure you preserve existing behavior (e.g.,
keep href/target) while preventing unhandled promise rejections.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.env:
- Line 1: The environment variable assignment for NEXT_PUBLIC_SITE_NAME
currently has spaces around the equals sign; update the .env entry for
NEXT_PUBLIC_SITE_NAME to use a direct KEY=value format (no spaces around '=') so
dotenv/shell parsers and linters accept it and the variable is read correctly.

In `@models/User/Session.ts`:
- Around line 61-69: The signOut function can throw if clear() (IndexedDB
cleanup) rejects, causing unhandled rejections and preventing the subsequent
reload; update async signOut(reload = false) to catch and swallow errors from
clear() (e.g., try { await clear(); } catch (err) { /* log/warn but continue */
}) so failures in clear() do not block this.user reset or the optional
location.reload(), and add a minimal debug log inside the catch to aid
diagnosis; ensure callers in pages/user/[id].tsx and components/User/UserBar.tsx
can continue to call signOut() without surrounding error handling.

In `@pages/_app.tsx`:
- Line 50: The call sessionStore.getProfile().catch(console.debug) uses
console.debug which violates the no-console rule; replace it with an allowed
logger or remove the catch handler. Update the catch to use an approved method
(e.g., sessionStore.getProfile().catch(err => logger.warn('getProfile failed',
err)) or .catch(err => console.info(err)) if a shared logger isn't available),
or remove the .catch entirely if upstream handles errors; locate the occurrence
by searching for sessionStore.getProfile() in the file and change the catch
argument from console.debug to an allowed logger method (warn/info/error) or a
no-op.

In `@pages/user/`[id].module.less:
- Line 33: Stylelint flags the CSS Modules :global(...) pseudo-class as unknown
for selectors like :global(.nav-link) (and the other :global(...) at the later
selector). Add an inline stylelint disable comment immediately above each
offending selector, e.g. /* stylelint-disable-next-line
selector-pseudo-class-no-unknown */ so stylelint ignores the :global
pseudo-class for those lines, or alternatively update project stylelint config
to allow the :global pseudo-class if you prefer a global fix; target the
specific selectors :global(.nav-link) and the other :global(...) occurrences
when applying the change.

In `@pages/user/me.tsx`:
- Line 24: Add a blank line before the existing "return result;" statement to
satisfy the `@stylistic/padding-line-between-statements` rule; locate the return
of the variable "result" in the function or component that contains "return
result;" and insert one empty line immediately above it.

---

Nitpick comments:
In `@pages/user/`[id].tsx:
- Around line 114-121: The onClick currently calls the async
sessionStore.signOut() without awaiting or handling rejections; update each call
site (sessionStore.signOut() in pages/user/[id].tsx and both occurrences in
components/User/UserBar.tsx) to explicitly handle the returned promise — either
make the onClick handler async and await sessionStore.signOut() inside a
try/catch that logs or handles errors, or append .catch(...) to the promise to
swallow/log failures; ensure you preserve existing behavior (e.g., keep
href/target) while preventing unhandled promise rejections.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6c451233-02c6-4635-80c3-3374b6082be9

📥 Commits

Reviewing files that changed from the base of the PR and between b2c26b9 and 38f018f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • .env
  • components/User/UserBar.tsx
  • models/Activity/Award.ts
  • models/User/Session.ts
  • package.json
  • pages/_app.tsx
  • pages/api/core.ts
  • pages/user/[id].module.less
  • pages/user/[id].tsx
  • pages/user/me.tsx
  • tsconfig.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • pages/api/core.ts

Comment thread .env
@@ -1,4 +1,4 @@
NEXT_PUBLIC_SITE_NAME = 开放黑客松
NEXT_PUBLIC_SITE_NAME = 黑客松开放平台
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove spaces around = in env assignment.

Line 1 uses KEY = value; prefer KEY=value to avoid parser/shell compatibility issues and satisfy dotenv linting.

Proposed fix
-NEXT_PUBLIC_SITE_NAME = 黑客松开放平台
+NEXT_PUBLIC_SITE_NAME=黑客松开放平台
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
NEXT_PUBLIC_SITE_NAME = 黑客松开放平台
NEXT_PUBLIC_SITE_NAME=黑客松开放平台
🧰 Tools
🪛 dotenv-linter (4.0.0)

[warning] 1-1: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.env at line 1, The environment variable assignment for
NEXT_PUBLIC_SITE_NAME currently has spaces around the equals sign; update the
.env entry for NEXT_PUBLIC_SITE_NAME to use a direct KEY=value format (no spaces
around '=') so dotenv/shell parsers and linters accept it and the variable is
read correctly.

Comment thread models/User/Session.ts
Comment on lines +61 to 69
async signOut(reload = false) {
setCookie('token', '', { path: '/', expires: new Date() });
setCookie('JWT', '', { path: '/', expires: new Date() });

this.user = undefined;
await sleep();
await clear();

if (reload) location.reload();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In idb-keyval v6.x, can clear() reject when IndexedDB is unavailable or blocked (e.g., private mode / storage restrictions)?

💡 Result:

Yes. In idb-keyval v6.x, clear returns a Promise that rejects if the underlying IndexedDB request/transaction fails (which includes cases where IndexedDB can’t be opened/used due to privacy/storage restrictions).

Citations:


🏁 Script executed:

# First, locate and read the Session.ts file around the target lines
fd -t f "Session.ts" -x wc -l {}

Repository: FreeCodeCamp-Chengdu/HOP

Length of output: 96


🏁 Script executed:

# Read the file content around lines 61-69
fd -t f "Session.ts" -x head -75 {} | tail -20

Repository: FreeCodeCamp-Chengdu/HOP

Length of output: 518


🏁 Script executed:

# Also check the imports and structure
fd -t f "Session.ts" -x head -10 {}

Repository: FreeCodeCamp-Chengdu/HOP

Length of output: 542


🏁 Script executed:

# Search for signOut call sites
rg "signOut\(" --type ts --type tsx -B 2 -A 2

Repository: FreeCodeCamp-Chengdu/HOP

Length of output: 96


🏁 Script executed:

# Search for signOut call sites (without tsx type filter)
rg "signOut\(" --type ts -B 2 -A 2

Repository: FreeCodeCamp-Chengdu/HOP

Length of output: 1326


🏁 Script executed:

# Also try broader search for .tsx files
rg "signOut\(" -B 2 -A 2 | head -50

Repository: FreeCodeCamp-Chengdu/HOP

Length of output: 1326


Harden sign-out against IndexedDB cleanup failures.

signOut() is async and awaits clear() at line 67, but all call sites invoke it without error handling (pages/user/[id].tsx and components/User/UserBar.tsx click handlers). When IndexedDB is unavailable or blocked (private mode, storage restrictions), clear() rejects, causing an unhandled promise rejection and preventing line 69's reload from executing.

🛡️ Suggested resilient implementation
 async signOut(reload = false) {
   setCookie('token', '', { path: '/', expires: new Date() });
   setCookie('JWT', '', { path: '/', expires: new Date() });

   this.user = undefined;
   await sleep();
-  await clear();
+  if (!isServer()) {
+    try {
+      await clear();
+    } catch {
+      // Keep sign-out successful even if client storage cleanup fails
+    }
+  }

-  if (reload) location.reload();
+  if (reload && !isServer()) location.reload();
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async signOut(reload = false) {
setCookie('token', '', { path: '/', expires: new Date() });
setCookie('JWT', '', { path: '/', expires: new Date() });
this.user = undefined;
await sleep();
await clear();
if (reload) location.reload();
async signOut(reload = false) {
setCookie('token', '', { path: '/', expires: new Date() });
setCookie('JWT', '', { path: '/', expires: new Date() });
this.user = undefined;
await sleep();
if (!isServer()) {
try {
await clear();
} catch {
// Keep sign-out successful even if client storage cleanup fails
}
}
if (reload && !isServer()) location.reload();
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@models/User/Session.ts` around lines 61 - 69, The signOut function can throw
if clear() (IndexedDB cleanup) rejects, causing unhandled rejections and
preventing the subsequent reload; update async signOut(reload = false) to catch
and swallow errors from clear() (e.g., try { await clear(); } catch (err) { /*
log/warn but continue */ }) so failures in clear() do not block this.user reset
or the optional location.reload(), and add a minimal debug log inside the catch
to aid diagnosis; ensure callers in pages/user/[id].tsx and
components/User/UserBar.tsx can continue to call signOut() without surrounding
error handling.

Comment thread pages/_app.tsx
if (tips) alert(tips);
});

sessionStore.getProfile().catch(console.debug);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Replace console.debug with an allowed logger (or remove it).

Line 50 violates no-console (only warn, error, info are allowed in this config).

✅ Minimal lint-safe patch
-    sessionStore.getProfile().catch(console.debug);
+    sessionStore.getProfile().catch(console.info);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
sessionStore.getProfile().catch(console.debug);
sessionStore.getProfile().catch(console.info);
🧰 Tools
🪛 ESLint

[error] 50-50: Unexpected console statement. Only these console methods are allowed: warn, error, info.

(no-console)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pages/_app.tsx` at line 50, The call
sessionStore.getProfile().catch(console.debug) uses console.debug which violates
the no-console rule; replace it with an allowed logger or remove the catch
handler. Update the catch to use an approved method (e.g.,
sessionStore.getProfile().catch(err => logger.warn('getProfile failed', err)) or
.catch(err => console.info(err)) if a shared logger isn't available), or remove
the .catch entirely if upstream handles errors; locate the occurrence by
searching for sessionStore.getProfile() in the file and change the catch
argument from console.debug to an allowed logger method (warn/info/error) or a
no-op.

margin-bottom: 1.5rem;
border: none;

:global(.nav-link) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Stylelint is currently failing on CSS Modules :global selectors.

Line 33 and Line 47 trigger selector-pseudo-class-no-unknown, so this file won’t pass lint as configured.

💡 Local fix option in this file
 .custom-tabs {
   gap: 0.5rem;
   margin-bottom: 1.5rem;
   border: none;

+  /* stylelint-disable-next-line selector-pseudo-class-no-unknown */
   :global(.nav-link) {
@@
-    &:global(.active) {
+    /* stylelint-disable-next-line selector-pseudo-class-no-unknown */
+    &:global(.active) {
       background: `#2563eb`;
       color: white;
     }
   }
 }

Also applies to: 47-47

🧰 Tools
🪛 Stylelint (17.9.0)

[error] 33-33: Unknown pseudo-class selector ":global" (selector-pseudo-class-no-unknown)

(selector-pseudo-class-no-unknown)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pages/user/`[id].module.less at line 33, Stylelint flags the CSS Modules
:global(...) pseudo-class as unknown for selectors like :global(.nav-link) (and
the other :global(...) at the later selector). Add an inline stylelint disable
comment immediately above each offending selector, e.g. /*
stylelint-disable-next-line selector-pseudo-class-no-unknown */ so stylelint
ignores the :global pseudo-class for those lines, or alternatively update
project stylelint config to allow the :global pseudo-class if you prefer a
global fix; target the specific selectors :global(.nav-link) and the other
:global(...) occurrences when applying the change.

Comment thread pages/user/me.tsx
},
};
}
return result;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix lint rule before return result.

Line 24 is flagged by @stylistic/padding-line-between-statements; add a blank line before this return.

🧰 Tools
🪛 ESLint

[error] 24-24: Expected blank line before this statement.

(@stylistic/padding-line-between-statements)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pages/user/me.tsx` at line 24, Add a blank line before the existing "return
result;" statement to satisfy the `@stylistic/padding-line-between-statements`
rule; locate the return of the variable "result" in the function or component
that contains "return result;" and insert one empty line immediately above it.

@TechQuery TechQuery added feature New feature or request and removed enhancement Some improvements labels May 3, 2026
@TechQuery TechQuery changed the title feat: redesign profile pages and fix activity create layout [refactor] redesign User profile page & fix Activity create layout May 3, 2026
@TechQuery TechQuery merged commit 742d0dc into main May 3, 2026
4 checks passed
@TechQuery TechQuery deleted the feat/auth branch May 3, 2026 20:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

现代化 HOP(黑客松开放平台)个人主页 UI 样式

2 participants